package org.example.handler;


import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import org.example.domain.po.RpcRequestMessagePO;
import org.example.domain.po.RpcResponseMessagePO;
import org.example.utils.ServiceFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @description:
 * @author: feixiang.li
 * @date: 2025-01-02 22:17
 */
@Slf4j
@ChannelHandler.Sharable
public class RpcRequestMessageHandler extends SimpleChannelInboundHandler<RpcRequestMessagePO> {

    /**
     * 读事件-处理请求
     *
     * @param channelHandlerContext 通信上下文
     * @param rpcRequestMessagePO   请求消息
     * @throws Exception 异常信息
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcRequestMessagePO rpcRequestMessagePO) throws Exception {
        log.info("生产者-收到消费端发送到请求消息:{}", rpcRequestMessagePO);
        RpcResponseMessagePO responseMessage = new RpcResponseMessagePO();
        //设置请求的序号
        responseMessage.setSequenceId(rpcRequestMessagePO.getSequenceId());
        Object result = null;
        try {
            //通过名称从工厂获取本地注解了@RpcServer的实例
            Object service = ServiceFactory.serviceFactory.get(rpcRequestMessagePO.getInterfaceName());
            //获取方法     方法名，参数
            Method method = service.getClass().getMethod(rpcRequestMessagePO.getMethodName(), rpcRequestMessagePO.getParameterTypes());
            //调用
            result = method.invoke(service, rpcRequestMessagePO.getParameterValue());
            //设置返回值
            responseMessage.setReturnValue(result);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            log.error("调用出错", e);
            responseMessage.setExceptionValue(new Exception("远程调用出错:" + e.getMessage()));
        } finally {
            channelHandlerContext.writeAndFlush(responseMessage);
            ReferenceCountUtil.release(rpcRequestMessagePO);
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleState state = ((IdleStateEvent) evt).state();
            if (state == IdleState.READER_IDLE) {
                log.info("长时间未收到心跳包，断开连接...");
                ctx.close();
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}
